﻿package net.wangit.jdbc.database;

import java.sql.Types;

import net.wangit.jdbc.JDBCException;
import net.wangit.jdbc.Type;
import net.wangit.util.StringUtil;


public class MySQL extends Database {

	public MySQL() {
		registerType(Type.CHAR, Types.CHAR, "CHAR($p)");
		registerType(Type.VARCHAR, Types.VARCHAR, "VARCHAR($p)");
		registerType(Type.SMALLINT, Types.SMALLINT, "SMALLINT");
		registerType(Type.INTEGER, Types.INTEGER, "INTEGER");
		registerType(Type.BIGINT, Types.BIGINT, "BIGINT");
		registerType(Type.FLOAT, Types.FLOAT, "FLOAT");
		registerType(Type.DOUBLE, Types.DOUBLE, "DOUBLE PRECISION");
		registerType(Type.DECIMAL, Types.NUMERIC, "NUMERIC($p, $s)");
		registerType(Type.DATE, Types.DATE, "DATE");
		registerType(Type.TIME, Types.TIME, "TIME");
		registerType(Type.TIMESTAMP, Types.TIMESTAMP, "DATETIME");
		registerType(Type.CLOB, Types.LONGVARCHAR, "LONGTEXT");
		registerType(Type.BLOB, Types.BLOB, "LONGBLOB");
	}

	public int getTypeCode(int sqlTypeCode, String columnTypeName,
			int precision, int scale) throws JDBCException {
		switch (sqlTypeCode) {
		case Types.CHAR:
			return Type.CHAR;

		case Types.VARCHAR:
			return Type.VARCHAR;

		case Types.SMALLINT:
			return Type.SMALLINT;

		case Types.INTEGER:
			return Type.INTEGER;

		case Types.BIGINT:
			return Type.BIGINT;

		case Types.FLOAT:
			return Type.FLOAT;

		case Types.DOUBLE:
			return Type.DOUBLE;

		case Types.NUMERIC:
			return Type.DECIMAL;

		case Types.DATE:
			return Type.DATE;

		case Types.TIME:
			return Type.TIME;

		case Types.TIMESTAMP:
			return Type.TIMESTAMP;

		case Types.LONGVARCHAR:
			return Type.CLOB;

		case Types.LONGVARBINARY:
			return Type.BLOB;
		}
		throw new JDBCException((new StringBuilder(
				"Unsupported sqlType: sqlTypeCode=")).append(sqlTypeCode)
				.append(",columnTypeName=").append(columnTypeName).toString());
	}

	public int getDefaultBatchSize() {
		return 15;
	}

	public String getAddColumnString() {
		return "add column";
	}

	public boolean supportsIdentityColumns() {
		return true;
	}

	public String getIdentitySelectString() {
		return "SELECT LAST_INSERT_ID()";
	}

	public String getIdentityColumnString() {
		return "NOT NULL AUTO_INCREMENT";
	}

	public String getAddForeignKeyConstraintString(String constraintName,
			String foreignKey[], String referencedTable, String primaryKey[]) {
		String cols = StringUtil.join(", ", foreignKey);
		return (new StringBuffer(30)).append(" add index (").append(cols)
				.append("), add constraint ").append(constraintName).append(
						" foreign key (").append(cols).append(") references ")
				.append(referencedTable).append(" (").append(
						StringUtil.join(", ", primaryKey)).append(')')
				.toString();
	}

	public String getCountSql(String sql) {
		int index = sql.indexOf(" from ");
		return (new StringBuilder("select count(*)")).append(
				sql.substring(index)).toString();
	}

	public boolean supportsLimit() {
		return true;
	}

	public String getLimitString(String sql, boolean hasOffset) {
		return (new StringBuffer(sql.length() + 20)).append(sql).append(
				hasOffset ? " limit ?, ?" : " limit ?").toString();
	}

	public char closeQuote() {
		return '`';
	}

	public char openQuote() {
		return '`';
	}

	public boolean supportsIfExistsBeforeTableName() {
		return true;
	}

	public String getSchemaSeparator() {
		return "_";
	}
}
